package topic.impl;

import interfaces.Subscriber;

import java.rmi.RemoteException;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;

import javax.rmi.PortableRemoteObject;
import javax.swing.tree.DefaultMutableTreeNode;

import lifecyclemanager.CacheLifeCycleManagerListener;
import lifecyclemanager.impl.CacheLifeCycleManagerListenerImpl;

import org.omg.CORBA.Object;
import org.omg.PortableServer.POA;

import topic.Topic;
import topic._Topic_Stub;

import accessers.DataReader;
import accessers.impl.DataReaderImpl;

import data.DataObject;
import embeded.EmbededObject;

/**
 * 
 * @author DOUMBOUYA
 * 
 */
public class TopicImpl implements topic.Topic {
	private Hashtable<String, Topic> topics;
	private DataObject data;
	private String name;
	private String fullName;
	private Subscriber suscriber;
	private DataReader dataReader;
//	private CacheLifeCycleManagerListener cachelifecycle;
	private static int ic = 0;
	private POA poa;

	// private LocalDomaineManagerImpl domaine;
	private EmbededObject domaine = null;

	public void setEmbededObject(EmbededObject domaine) throws RemoteException {
		this.domaine = domaine;
//		cachelifecycle = CacheLifeCycleManagerListenerImpl.getInstance();
	}

	// TODO Auto-generated method stub

	public void setSuscriber(Subscriber suscriber) throws RemoteException {
		this.suscriber = suscriber;
	}

	/**
	 * constructeur
	 * 
	 * @param name
	 *            : nom
	 * @param parent
	 *            : son parent
	 */
	public TopicImpl(String name, String parent, POA poa) {
		ic++;
		this.name = name;
		if (parent.equals(""))
			this.fullName = name;
		else
			this.fullName = parent + "." + name;
		this.dataReader = new DataReaderImpl(this);
		topics = new Hashtable<String, Topic>();
		data = new DataObject();
		this.poa = poa;
	}

	public TopicImpl(String name, String parent, POA poa, DataObject data) {
		this(name, parent, poa);
		this.data = data;
	}

	/**
	 * 
	 * @return : datareader du topic
	 */
	public DataReader getDataReader() throws RemoteException {
		return this.dataReader;
	}

	/**
	 * 
	 * @return
	 */
	public DefaultMutableTreeNode createNode() throws RemoteException {
		DefaultMutableTreeNode node;
		node = new DefaultMutableTreeNode(name + " : '" + data.getString()
				+ "'");
		Set<String> keys = topics.keySet();
		Iterator<String> strings = keys.iterator();
		while (strings.hasNext()) {
			String x = strings.next();
			DefaultMutableTreeNode node1 = topics.get(x).createNode();
			node.add(node1);
		}
		return node;
	}

	public DataObject getDataObject() throws RemoteException {
		return data;
	}

	public void setDataObject(DataObject data) throws RemoteException {
		this.data = data;
	}

	public String getName() throws RemoteException {
		return name;
	}

	/**
	 * 
	 * @param topicName
	 *            : nom du topic a rechercher
	 * @return : subscriber correspondant au topic
	 */
	public Subscriber getSuscriberWithPath(String topicName)
			throws RemoteException {
		int x = topicName.indexOf(".");
		if (x < 0) {
			TopicImpl topic = (TopicImpl) topics.get(topicName);
			if (topic == null)
				return null;
			return topic.getSuscriber();
		}
		String topicN = topicName.substring(0, x);
		TopicImpl topic = (TopicImpl) topics.get(topicN);
		if (topic == null)
			return null;
		return topic.getSuscriberWithPath(topicName.substring(x + 1,
				topicName.length()));
	}

	// //
	public Subscriber getSuscriber() throws RemoteException {
		/*
		 * SuscriberPOATie suscriber = new SuscriberPOATie(this.suscriber);
		 * Object obj = CorbaManager.getInstance().publish(suscriber,
		 * "suscriber " + ic); return SuscriberHelper.narrow(obj);
		 */
		return suscriber;
	}

	public boolean addTopic(String topicName, Topic topic, boolean isCopie)
			throws RemoteException {
		try {
			topic.setRootName(fullName);
			if (!isCopie) {
				topic.setEmbededObject(domaine);
				topic.setSuscriber(domaine.getInterfaceManager()
						.addNewDataReaderListener(topic.getFullName(),
								topic.getDataReader()));
			}
			boolean res = topics.put(topicName, topic) != null;
			if (!isCopie) {
				if (domaine != null)
					domaine.showFrame();
//				cachelifecycle.notifyCacheCreation(this, "");
			}
			return res;
		} catch (Exception e) {
			System.out.println("TopicImpl : error adding topic");
			e.printStackTrace();
			return false;
		}
	}
	
	public void initAllTopic(EmbededObject embeded) throws RemoteException {
		this.setEmbededObject(embeded);
		this.setSuscriber(embeded.getInterfaceManager().addNewDataReaderListener(this.fullName, this.dataReader));
//		cachelifecycle.notifyCacheCreation(this, "");
		for (int i = 0; i < getChildreenCount(); i++) {
			getChildreen().get(getChildreen().keySet().toArray()[i]).initAllTopic(embeded);
		}
	}

	public Topic getAllTopic() throws RemoteException {
	//	System.out.println("entre");
		Topic t = new TopicImpl(getName(), getFullName().substring(0,
				getFullName().lastIndexOf(".") + 1), poa), t1;
		t.setDataObject(getDataObject());
		for (int i = 0; i < getChildreenCount(); i++) {
			t1 = getChildreen().get(getChildreen().keySet().toArray()[i]);
			t.addTopic(t1.getName(), t1.getAllTopic(), true);
		}

		_TopicImpl_Tie tie = new _TopicImpl_Tie();
		tie.setTarget(t);
		Object obj;
		try {
			obj = poa.servant_to_reference(tie);
			Topic topic = (Topic) PortableRemoteObject.narrow(obj,
					Topic.class);
			return topic;
		} catch (Exception e) {
			e.printStackTrace();
			return t;
		}
	}

	public boolean deleteTopic(String topicName) throws RemoteException {
		try {
			boolean res = topics.remove(topicName) != null;
			if (domaine != null)
				domaine.showFrame();
//			cachelifecycle.notifyCacheDelete(this, "");
			return res;
		} catch (Exception e) {
			System.out.println("TopicImpl : error deleting topic");
			e.printStackTrace();
			return false;
		}
	}

	@Override
	public String toString() {
		return name;
	}

	/**
	 * 
	 * @return : nom absolu du topic
	 */
	public String getFullName() throws RemoteException {
		return fullName;
	}

	public void setRootName(String rootName) throws RemoteException {
		this.fullName = rootName + "." + name;
	}

	public int getChildreenCount() throws RemoteException {
		return topics.size();
	}

	public Hashtable<String, Topic> getChildreen() throws RemoteException {
		return topics;
	}

	public Topic contain(String topicName) throws RemoteException {
		topicName = topicName.substring(topicName.indexOf(".") + 1);
		if (topics.containsKey(topicName))
			return this.topics.get(topicName);
		Topic temp_Topic, result_Topic;
		for (int i = 0; i < topics.size(); i++) {
			temp_Topic = topics.get(topics.keySet().toArray()[i]);
			result_Topic = temp_Topic.contain(topicName);
			if (result_Topic != null)
				return result_Topic;
		}
		return null;
	}
}
